// ==UserScript==
// @name         币安 Alpha 撸毛助手
// @namespace    https://imgozi.cn/
// @version      0.1
// @description  币安 Alpha 撸毛助手，自动买卖直到设定的目标，每日统计
// @author       Gozi
// @match        https://www.binance.com/zh-CN/alpha/
// @match        https://www.binance.com/zh-CN/alpha/*
// @grant        none
// @run-at       document-idle
// @license      MIT
// ==/UserScript==

(function () {
  "use strict";

  const loadConfig = (confDef) => {
    const raw = localStorage.getItem("__$alpha__config__");
    try {
      const conf = JSON.parse(raw);
      Object.assign(config, conf || confDef || {});
    } catch (err) {}
  };
  const saveConfig = (conf) => {
    localStorage.setItem("__$alpha__config__", JSON.stringify(conf || config));
  };
  /**
   * 配置
   */
  const config = {
    // 交易币种
    tradeSymbol: "ZKJ",
    // 每次交易金额
    tradeAmount: 1000,
    // 每轮交易上限
    // tradeTarget: 8291,
    slipingPage: "0.1",
    //
    symbolSearchDelay: 500, // 输入搜索内容后的等待时间 (毫秒)
    // 窗口位置
    panelPosition: {
      x: null,
      y: null,
      width: null,
      height: null,
      lastUpdated: null,
    },
    // 统计数据 (只在当前会话有效)
    stats: {
      tradeCount: 0,       // 交易次数
      totalBuyAmount: 0    // 买入总金额
    }
  };
  // 加载本地配置
  loadConfig();

  // ========================================
  //
  //     Start 工具函数
  //
  // ----------------------------------------

  const __timestamp = (input) => {
    const date = input ? new Date(input) : new Date();

    const pad = (n) => n.toString().padStart(2, "0");

    return (
      [date.getFullYear(), pad(date.getMonth() + 1), pad(date.getDate())].join(
        "-"
      ) +
      " " +
      [
        pad(date.getHours()),
        pad(date.getMinutes()),
        pad(date.getSeconds()),
      ].join(":")
    );
  };

  const log = (...args) => {
    const ts = __timestamp();
    window["console"].log(`::>> [${ts}]`, ...args);
  };
  const error = (...args) => {
    const ts = __timestamp();
    window["console"].error(`::>> [${ts}]`, ...args);
  };

  const $ = (a, b) => {
    return typeof a === "string"
      ? document.querySelector(a)
      : a.querySelector(b);
  };
  const $$ = (a, b) => {
    return typeof a === "string"
      ? document.querySelectorAll(a)
      : a.querySelectorAll(b);
  };

  const sleep = (msec) => {
    return new Promise((resolve) => {
      setTimeout(() => {
        resolve(true);
      }, msec);
    });
  };

  /**
   * 等待特定元素出现
   *
   * @param {*} selector
   * @param {*} timeout
   * @param {*} condition  自定义条件
   * @returns
   */
  const waitFor = (selector, timeout = 10000, condition) => {
    log(`等待元素: ${selector}`);
    return new Promise((resolve, reject) => {
      const intervalTime = 100;
      let elapsedTime = 0;
      const interval = setInterval(() => {
        const element = document.querySelector(selector);
        const success =
          (element && !condition) ||
          (element && condition && condition(element) !== false);
        if (success) {
          clearInterval(interval);
          log(`找到元素: ${selector}`);
          resolve(element);
        } else {
          elapsedTime += intervalTime;
          if (elapsedTime >= timeout) {
            clearInterval(interval);
            error(`[助手] 元素 ${selector} 在 ${timeout}ms 后未找到`);
            reject(
              new Error(`Element ${selector} not found after ${timeout}ms`)
            );
          }
        }
      }, intervalTime);
    });
  };

  /**
   * 点击元素
   *
   * @param {*} selector
   * @param {*} delay
   */
  const click = async (selector, delay) => {
    const element = typeof selector === "string" ? $(selector) : selector;
    log("[ASSIST][click]", selector, element);
    await element.click();
    if (delay) {
      await sleep(delay);
    }
  };

  /**
   * 模拟输入
   *
   * @param {string | Element} element Input or Textarea
   * @param {*} text
   * @param {*} delay 后延迟
   */
  const input = async (element, text, delay) => {
    text = String(text);
    element = typeof element === "string" ? $(element) : element;
    log(
      `[ASSIST][input]: ${text} 到 ${
        element.placeholder || element.id || element.name || element.tagName
      }`
    );
    // number 类型不支持设置选区, 会导致无法模拟输入
    const isNumber = element.attributes.type?.value === "number";
    if (isNumber) {
      element.attributes.type.value = "text";
    }
    element.focus();
    await sleep(50);
    element.value = ""; // 先清空
    element.dispatchEvent(new Event("input", { bubbles: true })); // 触发input事件，让框架知道值变了
    await sleep(50);

    for (const char of text) {
      element.dispatchEvent(
        new KeyboardEvent("keydown", { key: char, bubbles: true })
      );
      element.dispatchEvent(
        new KeyboardEvent("keypress", { key: char, bubbles: true })
      );
      const start = element.selectionStart || 0;
      const end = element.selectionEnd || 0;
      element.setRangeText(char, start, end, "end");
      element.dispatchEvent(new Event("input", { bubbles: true }));
      element.dispatchEvent(
        new KeyboardEvent("keyup", { key: char, bubbles: true })
      );
      await sleep(Math.floor(30 + Math.random() * 40));
      // 模拟打字随机延时
    }
    element.dispatchEvent(new Event("change", { bubbles: true }));

    if (isNumber) {
      element.attributes.type.value = "number";
    }
    log("[助手] 模拟输入完成。");
    if (delay) {
      await sleep(delay);
    }
  };

  // ----------------------------------------
  //
  //     End 工具函数
  //
  // ========================================

  // ========================================
  //
  //     Start 设置交易界面, 将页面设置为待交易币种页面
  //
  // ----------------------------------------

  const setupTradingPage = async (symbol) => {
    try {
      // 1. 等待搜索框出现
      const searchInput = await waitFor(
        'input.bn-textField-input[placeholder="代币名称或合约地址"]'
      );
      log("[助手] 搜索框已找到。");

      // 2. 在搜索框输入目标代币符号
      await input(searchInput, symbol);
      log(`已在搜索框输入: ${symbol}`);

      // 3. 等待搜索结果加载
      log(`等待 ${config.symbolSearchDelay}ms 让搜索结果加载...`);
      await sleep(config.symbolSearchDelay);

      // 4. 查找包含目标代币名称的div元素
      log(`开始在过滤后的列表中查找 ${symbol} 代币...`);
      const tokenDivs = document.querySelectorAll(
        "div.t-body3.text-PrimaryText"
      );
      let targetLink = null;

      for (const div of tokenDivs) {
        if (div.textContent.trim() === symbol) {
          let parentAnchor = div.closest("a");
          if (parentAnchor) {
            targetLink = parentAnchor;
            break;
          } else {
            error("没找查询到代币", symbol);
          }
        }
      }

      // 5. 如果找到了链接，就模拟点击
      if (targetLink) {
        log(`准备点击 ${symbol} 代币链接 (延时 500ms)...`);
        await sleep(500);
        targetLink.click();
        log(`已模拟点击 ${symbol} 代币链接！`);
      } else {
        log(`错误：在搜索结果中未能找到 ${symbol} 代币的链接。`);
      }
    } catch (error) {
      error("[助手] 执行搜索并点击操作时出错:", error);
    }
  };

  // ----------------------------------------
  //
  //     End 设置币种
  //
  // ========================================

  // ========================================
  //
  //     Start 填写买入信息
  //
  // ----------------------------------------

  const performTradeAction = async (direction) => {
    if (!["buy", "sell"].includes(direction)) {
      throw new Error(
        "performTradeAction 参数错误。direction 只能是 buy 或 sell"
      );
    }

    log("开始执行交易");
    try {
      // #0. 选择交易方向
      log("选择交易方向:", direction);
      // 买入/卖出
      if (direction === "buy") {
        // 买入
        await click(".bn-tab-list__buySell .bn-tab__buySell:first-child", 100);
      } else {
        // 卖出
        await click(".bn-tab-list__buySell .bn-tab__buySell:last-child", 100);
      }

      // #1. 选择价格模式
      log("选择报价方式: 即时");
      // 即时
      await click(
        ".bn-tabs.bn-tabs__buySell + div > div > div:first-child",
        100
      );
      // 限价
      // await click(
      //   ".bn-tabs.bn-tabs__buySell + div > div > div:last-child",
      //   100
      // );

      // #2. 输入交易金额
      let tradeAmount = config.tradeAmount;
      if (direction === "sell") {
        log("查询代币可用余额");
        const balanceNode = await waitFor(
          ".bn-tabs__buySell + div + div > div:first-child"
        );
        const balance = balanceNode.innerText
          .split("\n")[2]
          .split(" ")[0]
          .replace(/[^\d\.]/g, "");
        if (parseFloat(balance) === 0) {
          alert("代币可用余额不能为 0");
          return Promise.resolve(false);
        }
        tradeAmount = balance;
        log("代币可用余额: ", balance);
      }
      const amountInput = await waitFor("#fromCoinAmount");
      await sleep(200);
      await input(amountInput, tradeAmount, 1000);
      log("设置交易金额: ", tradeAmount);

      // #3. 设置交易优先级模式及交易滑点
      log("准备优先级设置");
      const selPriorityMode =
        ".bn-tabs.bn-tabs__buySell + div + div + div + div + div";
      await waitFor(selPriorityMode, 10000, (ele) => {
        return ele.innerText.indexOf("--") === -1;
      });
      log("打开优先模式弹窗");
      await click(selPriorityMode + " .cursor-pointer");
      await waitFor(".bn-modal");
      await sleep(800);
      // 选择自定义
      log("选择自定义模式");
      await waitFor(".bn-modal .bn-modal-content > div > div:nth-child(3)");
      await click(".bn-modal .bn-modal-content > div > div:nth-child(3)", 500);
      // 输入自定义滑点
      await waitFor("#customize-slippage");
      await sleep(500);
      log("设置交易滑点: ", config.slipingPage);
      await input("#customize-slippage", config.slipingPage, 800);
      // 确认自定义模式
      await waitFor(".bn-modal-footer button");
      log("确认优先模式: 自定义");
      await click(
        ".bn-modal-footer button",
        300 + Math.floor(Math.random() * 300)
      );
      log("完成优先级设置: 自定义, 交易滑点:", config.slipingPage);

      // #3. 确认交易信息并上报
      log("打开交易信息确认弹窗");
      const tradeButton =
        direction === "buy"
          ? ".bn-button.bn-button__buy:not(.inactive)"
          : ".bn-button.bn-button__sell:not(.inactive)";
      await waitFor(tradeButton); // 确保按钮区域已加载
      await sleep(250);
      await click(tradeButton, 100);
      log(`${direction} 交易确认弹窗已打开。`);

      // 更新统计数据
      if (direction === "buy") {
        config.stats.tradeCount++;
        config.stats.totalBuyAmount += parseFloat(tradeAmount);
        log(`统计数据更新: 交易次数=${config.stats.tradeCount}, 买入总金额=${config.stats.totalBuyAmount}`);
      }
    } catch (err) {
      error(`执行 ${direction} 方向交易时出错:`, err);
      return Promise.resolve(false);
    }

    return Promise.resolve(true);
  };

  // ----------------------------------------
  //
  //     End 填写买入信息
  //
  // ========================================

  // ========================================
  //
  //     Start 下单
  //
  // ----------------------------------------

  // 等待确认按钮变为可用的函数
  const __waitInterval = 500;
  const waitForConfirmButtonEnabled = async (
    parentElement,
    timeout = __waitInterval
  ) => {
    const confirmButtonSelector = ".bn-modal-footer button.bn-button__primary";
    return new Promise((resolve, reject) => {
      let elapsedTime = 0;
      const interval = setInterval(() => {
        const confirmButton = parentElement.querySelector(
          confirmButtonSelector
        );
        if (confirmButton && !confirmButton.disabled) {
          clearInterval(interval);
          resolve(confirmButton);
        } else {
          elapsedTime += __waitInterval;
          if (elapsedTime >= timeout) {
            clearInterval(interval);
            if (confirmButton && confirmButton.disabled) {
              reject(new Error("确认按钮不可用"));
            } else if (!confirmButton) {
              reject(new Error("确认按钮未找到"));
            } else {
              reject(new Error("等待确认按钮超时"));
            }
          }
        }
      }, __waitInterval);
    });
  };

  // 主要执行函数：处理确认对话框
  const handleConfirmDialog = async () => {
    try {
      log("处理交易确认信息");
      const dialogSelector = 'div[role="dialog"][aria-label="modal"]';
      const dialogElement = await waitFor(dialogSelector);

      // 检查是否需要刷新
      log("检查是否需要更新");
      const refreshNoticeSelector = ".bg-Input .t-caption1.text-PrimaryText";
      const refreshLinkSelector = ".bg-Input .text-TextLink";
      const refreshNotice = dialogElement.querySelector(refreshNoticeSelector);

      if (refreshNotice && refreshNotice.textContent.includes("报价已更新")) {
        const refreshLink = dialogElement.querySelector(refreshLinkSelector);
        if (refreshLink) {
          log("报价过期，等待更新...");
          refreshLink.click();
        } else {
          log("报价过期，继续等待...");
        }
      } else {
        log("报价有效");
      }

      const confirmButton = await waitForConfirmButtonEnabled(dialogElement);
      confirmButton.click();
      log("交易已提交");
    } catch (error) {
      error(`确认交易时出错: ${error.message}`);
      error(error); // 打印完整错误栈
    }
  };

  // ----------------------------------------
  //
  //     End 下单
  //
  // ========================================

  // ========================================
  //
  //     Start UI 相关
  //
  // ----------------------------------------

  /**
   * 创建并初始化UI界面
   */
  const initUI = () => {
    // 重置统计数据（确保每次打开面板时都会清空统计数据）
    config.stats = {
      tradeCount: 0,       // 交易次数
      totalBuyAmount: 0    // 买入总金额
    };
    log("统计数据已重置");

    // 创建样式
    const style = document.createElement("style");
    style.textContent = `
      .alpha-trader-panel {
        position: fixed;
        top: 80px;
        right: 20px;
        background-color: #1e2329;
        border-radius: 8px;
        padding: 16px;
        width: 280px;
        border: 2px solid #f0b90b;
        z-index: 9999;
        font-family: 'PingFang SC', 'Microsoft YaHei', sans-serif;
        color: #eaecef;
        transition: all 0.3s ease;
      }
      .alpha-trader-panel.collapsed {
        width: auto;
        height: auto;
        padding: 8px;
        border: 2px solid #f0b90b; /* 确保折叠状态下边框一致 */
      }
      .alpha-trader-panel.collapsed .alpha-trader-content {
        display: none;
      }
      .alpha-trader-header {
        display: flex;
        justify-content: space-between;
        align-items: center;
        margin-bottom: 16px;
        cursor: move;
        white-space: nowrap;
      }
      .alpha-trader-title {
        color: #f0b90b;
        margin: 0;
        font-size: 16px;
        font-weight: 500;
        overflow: hidden;
        text-overflow: ellipsis;
        transition: transform 0.2s, text-shadow 0.2s;
      }
      .alpha-trader-toggle {
        background: none;
        border: none;
        color: #848e9c;
        cursor: pointer;
        font-size: 16px;
        padding: 4px;
        min-width: 20px;
        text-align: center;
        margin-left: 8px;
      }
      .alpha-trader-toggle:hover {
        color: #f0b90b;
      }
      .alpha-trader-form-group {
        margin-bottom: 12px;
      }
      .alpha-trader-label {
        display: block;
        margin-bottom: 6px;
        font-size: 12px;
        color: #848e9c;
      }
      .alpha-trader-input {
        width: 100%;
        padding: 8px;
        border: 1px solid #474d57;
        border-radius: 4px;
        background-color: #2b3139;
        color: #eaecef;
        font-size: 14px;
        box-sizing: border-box;
        transition: all 0.3s ease;
      }
      .alpha-trader-input:focus {
        outline: none;
        border-color: #f0b90b;
        box-shadow: 0 0 0 2px rgba(240, 185, 11, 0.2);
        background-color: #2f353f;
      }
      .alpha-trader-button-group {
        display: flex;
        gap: 8px;
        margin-top: 16px;
      }
      .alpha-trader-button {
        flex: 1;
        padding: 8px;
        border: none;
        border-radius: 4px;
        font-size: 14px;
        font-weight: 500;
        cursor: pointer;
        transition: all 0.2s ease;
        position: relative;
        overflow: hidden;
      }
      .alpha-trader-button:after {
        content: '';
        position: absolute;
        top: 50%;
        left: 50%;
        width: 5px;
        height: 5px;
        background: rgba(255, 255, 255, 0.5);
        opacity: 0;
        border-radius: 100%;
        transform: scale(1, 1) translate(-50%, -50%);
        transform-origin: 50% 50%;
      }
      .alpha-trader-button:hover:after {
        animation: ripple 0.6s ease-out;
      }
      @keyframes ripple {
        0% {
          transform: scale(0, 0);
          opacity: 0.5;
        }
        100% {
          transform: scale(20, 20);
          opacity: 0;
        }
      }
      .alpha-trader-button-buy {
        background-color: #0ecb81;
        color: white;
      }
      .alpha-trader-button-buy:hover {
        background-color: #0ca66e;
      }
      .alpha-trader-button-sell {
        background-color: #f6465d;
        color: white;
      }
      .alpha-trader-button-sell:hover {
        background-color: #e0364c;
      }
      .alpha-trader-status {
        margin-top: 12px;
        padding: 8px;
        border-radius: 4px;
        background-color: #2b3139;
        font-size: 12px;
        line-height: 1.4;
        max-height: 80px;
        overflow-y: auto;
      }
      .alpha-trader-status-item {
        margin-bottom: 4px;
        padding-bottom: 4px;
        border-bottom: 1px solid #474d57;
      }
      .alpha-trader-status-item:last-child {
        margin-bottom: 0;
        padding-bottom: 0;
        border-bottom: none;
      }
      .alpha-trader-timestamp {
        color: #848e9c;
        font-size: 10px;
      }
    `;
    document.head.appendChild(style);

    // 创建面板容器
    const panel = document.createElement("div");
    panel.className = "alpha-trader-panel";
    panel.innerHTML = `
      <div class="alpha-trader-header">
        <h3 class="alpha-trader-title">Alpha 撸毛助手 v0.1</h3>
        <button class="alpha-trader-toggle">−</button>
      </div>
      <div class="alpha-trader-content">
        <div class="alpha-trader-form-group">
          <label class="alpha-trader-label" for="alpha-tradeSymbol">交易币种</label>
          <input class="alpha-trader-input" type="text" id="alpha-tradeSymbol" placeholder="例如: ZKJ">
        </div>
        <div class="alpha-trader-form-group">
          <label class="alpha-trader-label" for="alpha-tradeAmount">单笔买入金额 (USDT)</label>
          <input class="alpha-trader-input" type="number" id="alpha-tradeAmount" placeholder="例如: 1000">
        </div>
        <!--
        <div class="alpha-trader-form-group">
          <label class="alpha-trader-label" for="alpha-tradeTarget">每轮交易上限 (USDT)</label>
          <input class="alpha-trader-input" type="number" id="alpha-tradeTarget" placeholder="例如: 8291">
        </div>
        -->
        <div class="alpha-trader-form-group">
          <label class="alpha-trader-label" for="alpha-slipingPage">最大滑点 (%)</label>
          <input class="alpha-trader-input" type="text" id="alpha-slipingPage" placeholder="例如: 0.1">
        </div>
        <div class="alpha-trader-button-group">
          <button class="alpha-trader-button alpha-trader-button-buy" id="alpha-buyButton">买入</button>
          <button class="alpha-trader-button alpha-trader-button-sell" id="alpha-sellButton">卖出</button>
        </div>
        <div class="alpha-trader-button-group" style="margin-top: 8px;">
          <button class="alpha-trader-button" id="alpha-statsButton" style="background-color: #474d57; color: white;">显示统计</button>
        </div>
        <div class="alpha-trader-status" id="alpha-statusLog">
          <div class="alpha-trader-status-item">
            <span class="alpha-trader-timestamp">[初始化]</span> 等待操作...
          </div>
        </div>
      </div>
    `;
    document.body.appendChild(panel);

    // 设置面板初始位置
    setTimeout(() => {
      // 获取面板尺寸
      const panelWidth = panel.offsetWidth;
      const panelHeight = panel.offsetHeight;

      // 尝试恢复保存的位置
      if (
        config.panelPosition &&
        config.panelPosition.x !== null &&
        config.panelPosition.y !== null
      ) {
        const pos = config.panelPosition;
        log("尝试恢复面板位置", pos);

        // 检查保存的位置是否在可视区域内
        if (isValidPosition(pos.x, pos.y, panelWidth, panelHeight)) {
          // 位置有效，恢复到保存的位置
          panel.style.left = `${pos.x}px`;
          panel.style.top = `${pos.y}px`;
          panel.style.right = "auto";
          log("已恢复面板位置");
        } else {
          // 位置无效，使用居中位置
          centerPanel();
          log("保存的位置无效，已重新居中");
        }
      } else {
        // 没有保存的位置，使用居中位置
        centerPanel();
        log("没有保存的位置，已居中显示");
      }
    }, 100); // 短暂延迟确保面板已渲染

    // 居中显示面板
    const centerPanel = () => {
      const windowWidth = window.innerWidth;
      const windowHeight = window.innerHeight;
      const panelWidth = panel.offsetWidth;
      const panelHeight = panel.offsetHeight;

      // 计算居中位置
      const left = Math.max(0, (windowWidth - panelWidth) / 2);
      const top = Math.max(0, (windowHeight - panelHeight) / 2);

      // 设置面板位置
      panel.style.left = `${left}px`;
      panel.style.top = `${top}px`;
      panel.style.right = "auto";

      // 保存居中位置
      savePanelPosition();
    };

    // 获取DOM元素
    const tradeSymbolInput = document.getElementById("alpha-tradeSymbol");
    const tradeAmountInput = document.getElementById("alpha-tradeAmount");
    // const tradeTargetInput = document.getElementById("alpha-tradeTarget");
    const slipingPageInput = document.getElementById("alpha-slipingPage");
    const buyButton = document.getElementById("alpha-buyButton");
    const sellButton = document.getElementById("alpha-sellButton");
    const statusLog = document.getElementById("alpha-statusLog");
    const toggleButton = panel.querySelector(".alpha-trader-toggle");

    // 添加日志函数
    const addUILog = (message) => {
      const now = new Date();
      const hours = now.getHours().toString().padStart(2, "0");
      const minutes = now.getMinutes().toString().padStart(2, "0");
      const seconds = now.getSeconds().toString().padStart(2, "0");
      const timestamp = `${hours}:${minutes}:${seconds}`;

      const logItem = document.createElement("div");
      logItem.className = "alpha-trader-status-item";
      logItem.innerHTML = `<span class="alpha-trader-timestamp">[${timestamp}]</span> ${message}`;

      statusLog.insertBefore(logItem, statusLog.firstChild);

      // 限制日志数量
      if (statusLog.children.length > 10) {
        statusLog.removeChild(statusLog.lastChild);
      }

      // 同时输出到控制台
      log(message);
    };

    // 加载配置到UI
    const loadConfigToUI = () => {
      tradeSymbolInput.value = config.tradeSymbol || "";
      tradeAmountInput.value = config.tradeAmount || "";
      // tradeTargetInput.value = config.tradeTarget || "";
      slipingPageInput.value = config.slipingPage || "";

      // 显示当前配置信息
      addUILog(
        `当前配置: ${config.tradeSymbol}, 金额: ${config.tradeAmount}, 滑点: ${config.slipingPage}%`
      );
    };

    // 防抖函数
    const debounce = (func, wait) => {
      let timeout;
      return function (...args) {
        const context = this;
        clearTimeout(timeout);
        timeout = setTimeout(() => func.apply(context, args), wait);
      };
    };

    // 从UI保存配置
    const saveConfigFromUI = debounce(() => {
      try {
        const newConfig = {
          tradeSymbol: tradeSymbolInput.value,
          tradeAmount: parseFloat(tradeAmountInput.value) || 0,
          // tradeTarget: parseFloat(tradeTargetInput.value) || 0,
          slipingPage: slipingPageInput.value || "0.1",
        };

        // 更新内存中的配置
        Object.assign(config, newConfig);

        // 保存到localStorage
        saveConfig(config);

        // 更新状态栏显示当前配置
        addUILog(
          `配置已更新: ${newConfig.tradeSymbol}, 金额: ${newConfig.tradeAmount}, 滑点: ${newConfig.slipingPage}%`
        );
      } catch (err) {
        addUILog(`保存配置出错: ${err.message}`);
      }
    }, 500); // 500ms防抖延迟

    // 立即保存配置（不使用防抖）
    const saveConfigNow = () => {
      try {
        const newConfig = {
          tradeSymbol: tradeSymbolInput.value,
          tradeAmount: parseFloat(tradeAmountInput.value) || 0,
          // tradeTarget: parseFloat(tradeTargetInput.value) || 0,
          slipingPage: slipingPageInput.value || "0.1",
        };

        // 更新内存中的配置
        Object.assign(config, newConfig);

        // 保存到localStorage
        saveConfig(config);

        return newConfig;
      } catch (err) {
        addUILog(`保存配置出错: ${err.message}`);
        return null;
      }
    };

    // 执行买入操作
    const uiPerformBuy = async () => {
      try {
        // 立即保存当前配置，不使用防抖
        const currentConfig = saveConfigNow();
        if (!currentConfig) return;

        // 执行买入
        addUILog(
          `开始执行买入操作: ${currentConfig.tradeSymbol}, 金额: ${currentConfig.tradeAmount} USDT`
        );
        const rst = await performBuy();
        log("performBuy 结果", rst);
        if (!rst) {
          addUILog("买入操作失败");
          return;
        }

        // 自动处理确认对话框
        setTimeout(async () => {
          try {
            await handleConfirmDialog();
          } catch (err) {
            addUILog(`处理确认对话框出错: ${err.message}`);
          }
        }, 1000);
      } catch (err) {
        addUILog(`执行买入操作出错: ${err.message}`);
      }
    };

    // 执行卖出操作
    const uiPerformSell = async () => {
      try {
        // 立即保存当前配置，不使用防抖
        const currentConfig = saveConfigNow();
        if (!currentConfig) return;

        // 执行卖出
        addUILog(
          `开始执行卖出操作: ${currentConfig.tradeSymbol}, 金额: ${currentConfig.tradeAmount} USDT`
        );
        const rst = await performSell();
        log("performSell 结果", rst);
        if (!rst) {
          addUILog("买出操作失败");
          return;
        }

        // 自动处理确认对话框
        setTimeout(async () => {
          try {
            await handleConfirmDialog();
          } catch (err) {
            addUILog(`处理确认对话框出错: ${err.message}`);
          }
        }, 1000);
      } catch (err) {
        addUILog(`执行卖出操作出错: ${err.message}`);
      }
    };

    // 折叠/展开面板
    const togglePanel = () => {
      panel.classList.toggle("collapsed");
      if (panel.classList.contains("collapsed")) {
        toggleButton.textContent = "+";
      } else {
        toggleButton.textContent = "−";
      }
    };

    // 实现面板拖动
    let isDragging = false;
    let dragOffsetX, dragOffsetY;

    panel
      .querySelector(".alpha-trader-header")
      .addEventListener("mousedown", (e) => {
        isDragging = true;
        dragOffsetX = e.clientX - panel.getBoundingClientRect().left;
        dragOffsetY = e.clientY - panel.getBoundingClientRect().top;
        panel.style.transition = "none";
      });

    document.addEventListener("mousemove", (e) => {
      if (isDragging) {
        // 计算新位置
        let x = e.clientX - dragOffsetX;
        let y = e.clientY - dragOffsetY;

        // 获取面板和窗口尺寸
        const rect = panel.getBoundingClientRect();
        const windowWidth = window.innerWidth;
        const windowHeight = window.innerHeight;

        // 边界检查，确保面板不会移出窗口
        // 左边界检查
        x = Math.max(0, x);
        // 上边界检查
        y = Math.max(0, y);
        // 右边界检查 (保留至少20px在可视区域内，确保用户可以拖回)
        x = Math.min(x, windowWidth - Math.min(rect.width, 20));
        // 下边界检查 (保留至少20px在可视区域内)
        y = Math.min(y, windowHeight - Math.min(rect.height, 20));

        // 应用新位置
        panel.style.left = `${x}px`;
        panel.style.top = `${y}px`;
        panel.style.right = "auto";
      }
    });

    // 检查位置是否在可视区域内
    const isValidPosition = (x, y, width, height) => {
      return (
        x >= 0 &&
        y >= 0 &&
        x + width <= window.innerWidth &&
        y + height <= window.innerHeight
      );
    };

    // 保存面板位置
    const savePanelPosition = () => {
      const rect = panel.getBoundingClientRect();
      config.panelPosition = {
        x: rect.left,
        y: rect.top,
        width: rect.width,
        height: rect.height,
        lastUpdated: Date.now(),
      };
      saveConfig();
      log("面板位置已保存", config.panelPosition);
    };

    document.addEventListener("mouseup", () => {
      if (isDragging) {
        isDragging = false;
        panel.style.transition = "all 0.3s ease";
        // 拖动结束后保存位置
        savePanelPosition();
      }
    });

    // 窗口大小变化时检查面板位置
    window.addEventListener("resize", () => {
      const pos = config.panelPosition;
      if (pos && pos.x !== null && pos.y !== null) {
        const rect = panel.getBoundingClientRect();
        if (!isValidPosition(pos.x, pos.y, rect.width, rect.height)) {
          // 如果位置无效，重新居中
          const windowWidth = window.innerWidth;
          const windowHeight = window.innerHeight;
          const left = Math.max(0, (windowWidth - rect.width) / 2);
          const top = Math.max(0, (windowHeight - rect.height) / 2);
          panel.style.left = `${left}px`;
          panel.style.top = `${top}px`;
          savePanelPosition();
        }
      }
    });

    // 显示统计数据
    const showStats = () => {
      console.log("=== Alpha 撸毛助手统计数据 ===");
      console.log(`交易次数: ${config.stats.tradeCount}`);
      console.log(`买入总金额: ${config.stats.totalBuyAmount} USDT`);
      console.log("===========================");

      addUILog(`已在控制台输出统计数据 (交易次数: ${config.stats.tradeCount}, 买入总金额: ${config.stats.totalBuyAmount} USDT)`);
    };

    // 绑定事件 - 使用input事件实现实时更新
    tradeSymbolInput.addEventListener("input", saveConfigFromUI);
    tradeAmountInput.addEventListener("input", saveConfigFromUI);
    // tradeTargetInput.addEventListener("input", saveConfigFromUI);
    slipingPageInput.addEventListener("input", saveConfigFromUI);
    buyButton.addEventListener("click", uiPerformBuy);
    sellButton.addEventListener("click", uiPerformSell);
    toggleButton.addEventListener("click", togglePanel);
    document.getElementById("alpha-statsButton").addEventListener("click", showStats);

    // 确保DOM元素完全加载后再初始化配置
    setTimeout(() => {
      // 初始加载配置
      loadConfigToUI();
    }, 100);

    // 返回面板元素，方便外部访问
    return {
      panel,
      addLog: addUILog,
      loadConfig: loadConfigToUI,
      saveConfig: saveConfigFromUI,
    };
  };

  // 封装买入和卖出操作
  const performBuy = async () => {
    try {
      await setupTradingPage(config.tradeSymbol);
      await performTradeAction("buy");
      //
      return Promise.resolve(true);
    } catch (err) {
      return Promise.resolve(false);
    }
  };

  const performSell = async () => {
    try {
      await setupTradingPage(config.tradeSymbol);
      await performTradeAction("sell");
      //
      return Promise.resolve(true);
    } catch (err) {
      return Promise.resolve(false);
    }
  };

  // ----------------------------------------
  //
  //     End UI 相关
  //
  // ========================================

  // 初始化UI
  const ui = initUI();
  log(`Alpha 助手UI已加载。`);

  window.$alpha = {
    config: (conf) => {
      if (!conf) {
        log("当前参数", config);
        return;
      }
      Object.assign(config, conf);
      // 如果UI已初始化，同步更新UI
      if (ui) {
        ui.loadConfig();
      }
    },
    //
    setupTradingPage,
    performTradeAction,
    performBuy,
    performSell,
    handleConfirmDialog,
    //
    sleep,
    waitFor,
    input,
  };
})();
